; ** por compatibilidad se omiten tildes **
; ==============================================================================
; TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
; ==============================================================================
; definicion de rutinas de atencion de interrupciones

%include "imprimir.mac"

BITS 32


; memoria que se utiliza
; para realizar el jmp far en un cambio de tarea
;
sched_tarea_offset:     dd 0x00
sched_tarea_selector:   dw 0x00

; funciones externas utilizadas
extern sched_proximo_indice
extern sched_idle
extern game_jugador_mover
extern game_cambiar_tipo_zombie
extern game_move_current_zombi
extern game_lanzar_zombi
extern game_desalojar_zombie_actual
extern setear_modo_debug
extern guardar_crs
extern imprimir_contexto_excepcion
	
;;
;; Mensajes para las interrupciones
;; -------------------------------------------------------------------------- ;;
MSG_INT0:      DB "Division por cero."
LONG_MSG_INT0  EQU $ - MSG_INT0

MSG_INT3:      DB "Punto de interrupcion (Breakpoint)."
LONG_MSG_INT3  EQU $ - MSG_INT3

MSG_INT4:      DB "Desbordamiento (Overflow)."
LONG_MSG_INT4  EQU $ - MSG_INT4

MSG_INT5:      DB "Limite de rango excedido."
LONG_MSG_INT5  EQU $ - MSG_INT5

MSG_INT6:      DB "Codigo de operacion invalido."
LONG_MSG_INT6  EQU $ - MSG_INT6

MSG_INT7:      DB "Dispositivo no disponible."
LONG_MSG_INT7  EQU $ - MSG_INT7

MSG_INT8:      DB "Doble falta."
LONG_MSG_INT8  EQU $ - MSG_INT8

MSG_INT9:      DB "Segmento del coprocesador excedido."
LONG_MSG_INT9  EQU $ - MSG_INT9

MSG_INT10:     DB "TSS no valido."
LONG_MSG_INT10 EQU $ - MSG_INT10

MSG_INT11:     DB "Segmento no presente."
LONG_MSG_INT11 EQU $ - MSG_INT11

MSG_INT12:     DB "Fallo sobre el segmento de pila."
LONG_MSG_INT12 EQU $ - MSG_INT12

MSG_INT13:     DB "Proteccion general."
LONG_MSG_INT13 EQU $ - MSG_INT13

MSG_INT14:     DB "Fallo de pagina."
LONG_MSG_INT14 EQU $ - MSG_INT14

MSG_INT16:     DB "Error de de punto flotante en la FPU."
LONG_MSG_INT16 EQU $ - MSG_INT16

MSG_INT17:     DB "Verificacion de alineacion."
LONG_MSG_INT17 EQU $ - MSG_INT17

MSG_INT18:     DB "Verificacion de maquina."
LONG_MSG_INT18 EQU $ - MSG_INT18

MSG_INT19:     DB "Excepcion de punto flotante en SIMD."
LONG_MSG_INT19 EQU $ - MSG_INT19

MSG_INT32:     DB "Reloj."
LONG_MSG_INT32 EQU $ - MSG_INT32

MSG_INT33:     DB "Teclado."
LONG_MSG_INT33 EQU $ - MSG_INT33

MSG_INT52:     DB "Servicios del Kernel."
LONG_MSG_INT52 EQU $ - MSG_INT52


;; PIC
extern fin_intr_pic1

;; Sched
extern sched_proximo_indice

;;
;; Definición de MACROS
;; -------------------------------------------------------------------------- ;;

%macro ISR 1
global _isr%1

_isr%1:
    cli
    pushfd 							 ; guarda del valor de los flags
    pushad

 
;   call pintar_pantalla_azul
;   imprimir_texto_mp MSG_INT%+%1, LONG_MSG_INT%+%1, 0x1F, 1, 1
    

    push dword LONG_MSG_INT%+%1
    push dword MSG_INT%+%1
    call imprimir_contexto_excepcion
    add esp, 8

    call game_desalojar_zombie_actual				; ya no hacemos que se pinte una
								; death screen of death
								; sino que desalojamos a la tarea
								; que arrojó la excepcion.

    call  sched_proximo_indice					; una vez que desalojamos la tarea
								; vemos cuál es el próximo índice
								; para hacer el swap
	

    mov [sched_tarea_selector], ax
    call fin_intr_pic1 						; le comunica al pic que ya se 
								; atendio la interrupción

    jmp FAR [sched_tarea_offset]				; realizamos el jmp far a la próxima
								; tarea

; .loopear:
;    mov eax, 0xFFFF
;    mov ebx, 0xFFFF
;    mov ecx, 0xFFFF
;    mov edx, 0xFFFF
;    jmp $

   
    popfd
    popad
    sti
    iret

%endmacro

;;
;; Datos
;; -------------------------------------------------------------------------- ;;
; Scheduler
isrnumero:           dd 0x00000000
isrClock:            db '|/-\'

;;
;; Rutina de atención de las EXCEPCIONES
;; -------------------------------------------------------------------------- ;;
ISR 0
ISR 3
ISR 4
ISR 5
ISR 6
ISR 7
ISR 8
ISR 9
ISR 10
ISR 11
ISR 12
ISR 13
ISR 14
ISR 16
ISR 17
ISR 18
ISR 19

;;
;; Rutina de atención del RELOJ
;; -------------------------------------------------------------------------- ;;
;------------------------------------------------------------------------
global _isr32



_isr32:  ; Reloj
	cli
	pushfd 					; guarda del valor de los flags
	pushad
	

	call proximo_reloj	

	call  sched_proximo_indice	        ; verificamos cual es el índice del gdt que tenemos que ejecutar
	
	str bx				        ; para evitar cambiar de tarea sin necesidad comparamos con el índice de tr

	cmp ax, bx
  	je .nojump

	mov [sched_tarea_selector], ax
	call fin_intr_pic1 		        ; le comunica al pic que ya se atendio la interrupción
  	jmp FAR [sched_tarea_offset]

	jmp .fin
.nojump:
	call fin_intr_pic1 		        ; le comunica al pic que ya se atendio la interrupción
.fin:	
	popad
	popfd 				        ; restablece el valor de los flags
	sti	
	iret 				        ; retorna de la interrupción

;;
;; Rutina de atención del TECLADO
;; -------------------------------------------------------------------------- ;;
global _isr33

_isr33:  ; Teclado.
	cli					; lo primero que hacemos es deshabilitar las int.
	pushfd 					; guarda del valor de los flags
	pushad

	call fin_intr_pic1 		       ; le comunica al pic que ya se atendio la interrupción

        xor eax, eax

	in al, 0x60				; se lee el caracter
	
	cmp al, 0x11				; se verifica que letra se leyo
	je .w					
	cmp al, 0x1F
	je .s
	cmp al, 0x20
	je .d	
	cmp al, 0x1E
	je .a	
	cmp al, 0x2A
	je .left_shift	
	cmp al, 0x17
	je .i	
	cmp al, 0x24
	je .j	
	cmp al, 0x25
	je .k	
	cmp al, 0x26
	je .l	
	cmp al, 0x36
	je .right_shift
	cmp al, 0x15
	je .y	
	jmp .fin
.w:
	mov al, 87
  	mov byte [GS:158], AL
	push dword 1
	push dword 0
	call game_jugador_mover	
	add esp, 8
	jmp .fin
.s:
	mov al, 83
  	mov byte [GS:158], AL
	push dword 0
	push dword 0
	call game_jugador_mover	
	add esp, 8
	jmp .fin
.d:
	push dword 0
	push dword 0
	call game_cambiar_tipo_zombie
	add esp, 8

	mov al, 68
  	mov byte [GS:158], AL
	jmp .fin	
.a:
	push dword 1
	push dword 0
	call game_cambiar_tipo_zombie
	add esp, 8

	mov al, 65  	
	mov byte [GS:158], AL
	jmp .fin	
.left_shift:
	push dword 0
	call game_lanzar_zombi
	add esp, 4
	mov al, 60
  	mov byte [GS:158], AL
	jmp .fin	
.i:
	mov al, 73
  	mov byte [GS:158], AL
	push dword 1
	push dword 1
	call game_jugador_mover	
	add esp, 8
	jmp .fin
.j:
	push dword 1
	push dword 1
	call game_cambiar_tipo_zombie
	add esp, 8

	mov al, 74
  	mov byte [GS:158], AL
	jmp .fin
.k:
	push dword 0
	push dword 1
	call game_jugador_mover	
	add esp, 8
	mov al, 75
  	mov byte [GS:158], AL
	jmp .fin	
.l:
	push dword 0
	push dword 1
	call game_cambiar_tipo_zombie
	add esp, 8
	mov al, 76
  	mov byte [GS:158], AL
	jmp .fin	
.right_shift:
	push dword 1
	call game_lanzar_zombi
	add esp, 4
	mov al, 62
  	mov byte [GS:158], AL
	jmp .fin	
.y:
	call setear_modo_debug
	mov al, 62
  	mov byte [GS:158], AL
.fin:
	popad
	popfd 				; restablece el valor de los registros de proposito general
	sti
	iret 				; retorna de la interrupción

;;
;; Rutinas de atención de las SYSCALLS
;; -------------------------------------------------------------------------- ;;

%define IZQ 0xAAA
%define DER 0x441
%define ADE 0x83D
%define ATR 0x732

global _isr102

_isr102:
	cli
	pushfd 				; guarda del valor de los flags
	pushad
	
;	mov eax, 0x42
	cmp eax, IZQ
	je .izq
	cmp eax, DER
	je .der
	cmp eax, ADE
	je .ade
	cmp eax, ATR
	je .atr
	jmp .fin
.izq:
	push dword 1
	call game_move_current_zombi
	add esp, 4
	jmp .fin
.der:
	push dword 0
	call game_move_current_zombi
	add esp, 4
	jmp .fin
.ade:
	push dword 3
	call game_move_current_zombi
	add esp, 4
	jmp .fin
.atr:
	push dword 2
	call game_move_current_zombi
	add esp, 4
.fin:
	call sched_idle

	pushad
	call guardar_crs
	popad

	mov [sched_tarea_selector], ax
 	jmp FAR [sched_tarea_offset]

	popad
	popfd 				; restablece el valor de los flags
	sti	
	iret 				; retorna de la interrupción


;; Funciones Auxiliares
;; -------------------------------------------------------------------------- ;;
proximo_reloj:
        pushad
        inc DWORD [isrnumero]
        mov ebx, [isrnumero]
        cmp ebx, 0x4
        jl .ok
                mov DWORD [isrnumero], 0x0
                mov ebx, 0
        .ok:
                add ebx, isrClock
                imprimir_texto_mp ebx, 1, 0x0f, 49, 79
                popad
        ret
        
pintar_pantalla_azul:

  	push ebp
  	mov ebp, esp  

  	mov ecx, 80*50  
  	xor edx, edx   ; Para desplazarnos en la memoria de video.

  .ciclo:
    	mov word [gs:edx], 0x1000
    	add edx, 2
  	loop .ciclo

  	pop ebp
  	ret
        
